package com.fast.fast.common.core.util;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.method.HandlerMethod;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;


/**
 * Web工具类
 *
 * @author lyf
 * @date 2022/01/01 00:00 周六
 */
@Slf4j
@UtilityClass
public class WebUtils extends org.springframework.web.util.WebUtils {

    /**
     * 判断是否为ajax请求,通过方法上是否有ResponseBody注解或者类上是否有RestController注解判断
     *
     * @param handlerMethod HandlerMethod
     * @return 是否为ajax请求
     */
    public boolean isAjax(HandlerMethod handlerMethod) {
        ResponseBody responseBody = ClassUtils.getAnnotation(handlerMethod, ResponseBody.class);
        RestController restController = ClassUtils.getAnnotation(handlerMethod, RestController.class);
        return responseBody != null || restController != null;
    }

    /**
     * 获取 HttpServletRequest
     *
     * @return {HttpServletRequest}
     */
    public HttpServletRequest getRequest() {
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (servletRequestAttributes == null) {
            throw new RuntimeException("非Web上下文无法获取Request");
        }
        return servletRequestAttributes.getRequest();
    }

    /**
     * 获取 HttpServletResponse
     *
     * @return {HttpServletResponse}
     */
    public HttpServletResponse getResponse() {
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (servletRequestAttributes == null) {
            throw new RuntimeException("非Web上下文无法获取Response");
        }
        return servletRequestAttributes.getResponse();
    }

    /**
     * 判断当前是否处于 Web 上下文中
     *
     * @return request
     */
    public static boolean isWeb() {
        return RequestContextHolder.getRequestAttributes() != null;
    }

    /**
     * 根据请求头的名称，获取请求头的值
     *
     * @param name header name
     * @return header value
     */
    public String getHeaderValueByName(String name) {
        return getRequest().getHeader(name);
    }

    /**
     * 获取所有cookie对象
     *
     * @return cookies
     */
    public Cookie[] getCookies() {
        return getRequest().getCookies();
    }

    /**
     * 获取可读的所有cookie对象
     *
     * @return {name:value}
     */
    public JSONObject getCookiesForReadable() {
        JSONObject jo = new JSONObject();
        Cookie[] cookies = getRequest().getCookies();
        for (Cookie cookie : cookies) {
            jo.put(cookie.getName(), cookie.getValue());
        }
        return jo;
    }

    /**
     * 根据cookie的名称，获取cookie对象
     *
     * @param name cookie name
     * @return cookie
     */
    public Cookie getCookieByName(String name) {
        return getCookie(getRequest(), name);
    }

    /**
     * 根据cookie的名称，获取cookie的值
     *
     * @param name cookie name
     * @return cookie value
     */
    public String getCookieValueByName(String name) {
        return getCookieByName(name).getValue();
    }

    /**
     * 设置cookie
     *
     * @param name            cookie name
     * @param value           cookie value
     * @param maxAgeInSeconds cookie 有效时间(秒)，-1表示会话级cookie，关闭浏览器该cookie会消失
     */
    public void setCookie(String name, String value, int maxAgeInSeconds) {
        Cookie cookie = new Cookie(name, value);
        cookie.setPath("/");
        cookie.setMaxAge(maxAgeInSeconds);
        cookie.setHttpOnly(true);
        getResponse().addCookie(cookie);
    }

    /**
     * 根据cookie的名称，清除cookie
     *
     * @param name cookie name
     */
    public void removeCookie(String name) {
        setCookie(name, null, 0);
    }

    /**
     * 将数据对象加入响应体并以json格式返回
     *
     * @param result 数据对象
     */
    public void renderJson(Object result) throws IOException {
        HttpServletResponse response = getResponse();
        response.setCharacterEncoding("UTF-8");
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        PrintWriter out = response.getWriter();
        out.append(JSON.toJSONString(result));
    }

}
